/*
自定义promise函数模块 
使用ES5 匿名函数自调用
*/


(function (window) {
    const PENDING = "pending";
    const RESOLVED = "resolved";
    const REJECTED = "rejected";
    /*
      创建promise构造函数
      excutor: 执行器函数（同步）
    */
    function Promise(excutor) {
        // 将promise对象保存起来
        const self = this

        self.status = PENDING   // 给promise对象添加一个状态的属性，初始值为“pending”
        self.data = undefined   // 给promise对象添加一个数据的属性，用来储存数据结果，初始值为undefined
        self.callBacks = []       // 给promise对象添加一个数组的属性，用来存放回调函数 ，初始为一个空数组



        function resolve(value) {
            // 如果状态不是pending 就不需要执行了 
            if (self.status !== PENDING) {
                return
            }

            // 状态该为 resolve
            self.status = RESOLVED

            // 接受数据value
            self.data = value

            // 可能会执行外部定义的回调函数
            //先判断是否有回调函数

            if (self.callBacks.length > 0) {
                setTimeout(() => { // 执行所有的成功的回调
                    self.callBacks.forEach(callBacksObj => {
                        callBacksObj.onResolved(value)
                    })
                });
            }
        }

        function reject(reason) {
            // 如果状态不是pending 就不需要执行了 
            if (self.status !== PENDING) {
                return
            }

            // 状态该为 resolve
            self.status = REJECTED

            // 接受数据value
            self.data = reason

            // 可能会执行外部定义的回调函数
            //先判断是否有回调函数
            if (self.callBacks.length > 0) {
                setTimeout(() => { // 执行所有的失败的回调
                    self.callBacks.forEach(callBacksObj => {
                        callBacksObj.onRejected(reason)
                    })
                });
            }
        }

        // 存在异常捕获
        try {
            excutor(resolve, reject)
        } catch (error) { // 如果捕获到异常，promise就变为reject状态
            reject(error)
        }


    }

    /*
     *Promise原型对象上的then()方法
     *指定成功和失败的回调函数
     *返回一个新的promise，
     */
    Promise.prototype.then = function (onResolved, onRejected) {

        // 指定默认的成功回调函数，如果onResolved不是函数，就把 value => value 作为回调函数传给onResolved
        onResolved = typeof onResolved === "function" ? onResolved : value => value;// 向下传递value

        // 指定默认的失败回调函数，如果onRejected不是函数，就把reason => {throw  reason}作为回调函数传给onResolved
        onRejected = typeof onRejected === "function" ? onRejected : reason => { throw reason } // 抛出错误reas

        const self = this // 存储promise对象
        
        return new Promise((resolve, reject) => { //返回一个新的promise
            

            // 封装一个基于指定回调函数执行结果返回promise对象状态的和值的函数模块
            function handle(callBack) {
               
                try {
                    const result = onResolved(self.data)
                    //回调函数执行有三种结果 ，
                    // 1，执行时抛出异常， 新返回的promise对象状态为reject ， 新返回的值为异常信息error
                    // 2，执行结果为非promise对象， 新返回的promise对象状态为resolve ，新返回的值就执行结果
                    // 3. 执行结果为promise对象， 新返回的promise对象就是执行结果的promise， 

                   

                    if (result instanceof Promise) { // 第3种
                        result.then(resolve, reject)
                    } else {      // 第2种
                        resolve(result)
                    }
                } catch (error) {  // 第1种
                    reject(error)
                }
            }

            if (self.status === RESOLVED) {  // 当前promise是resolved 
                setTimeout(() => { //异步执行成功的回调
                    handle(onResolved)

                });

            } else if (self.status === REJECTED) {  // 当前promise是rejected 
                setTimeout(() => { //异步执行失败的回调
                    handle(onRejected)

                });

            } else {  // 当前promise是peding 
                self.callBacks.push({
                    onResolved(value) {
                        handle(onResolved)
                    },
                    onRejected(reason) {
                        handle(onRejected)
                    }
                })

            }

        })

    }


    /*
     *Promise原型对象上的catch()方法
     *指定失败的回调函数
     *返回一个新的promise，
     */
    Promise.prototype.catch = function (onRejected) {
        return this.then(undefined, onRejected)
    }

    /*
     *Promise构造函数对象上的all()方法
     *返回一个新的promise，所有的promise都成功才算成功， 有一个失败就算失败
     */
    Promise.all = function (promises) {
        const values = new Array(promises.length)

        let resolvedCount = 0

        return new Promise((resolve, reject) => {

            promises.forEach((p, index) => {
                p.then(
                    value => {
                        resolvedCount++
                        values[index] = value
                        if (resolvedCount === promises.length) {
                            resolve(values)
                        }

                    },
                    reason => {
                        reject(reason)
                    }

                )

            })

        })
    }

    /*
     *Promise构造函数对象上的race()方法
     *返回一个新的promise，所有的promise中最先执行完成的状态就是他的最终状态
     */
    Promise.race = function (promises) {

    }

    /*
     *Promise构造函数对象上的resolve()方法
     * 返回一个成功且值为value的新的promise对象
     */
    Promise.resolve = function (value) {
        return new Promise((resolve, reject) => {
            if (value instanceof Promise) {
                value.then(resolve, reject)
            } else {
                resolve(value)
            }
        })
    }

    /*
     *Promise构造函数对象上的reject()方法
     返回一个失败且错误信息为veason的新的promise对象
     */
    Promise.reject = function (reason) {
        return new Promise((resolve, reject) => {
            reject(reason)
        })
    }

    /*
     *向外暴露promise构造函数
     */


    window.Promise = Promise
})(window)